package ui.logger;

import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;

import javax.swing.UIManager;

import ui.logger.LogEvent.Types;

public class GlobalLogger implements LogAcceptor {
	private static final String BINDING_PROPERTIES = "./res/log.binding.properties";
	private Map<Class<? extends LogEvent>, LogAcceptor> acceptors = new HashMap<Class<? extends LogEvent>, LogAcceptor>();
	private static GlobalLogger instance;
	static {
		instance = new GlobalLogger();
	}

	@SuppressWarnings("unchecked")
	public GlobalLogger() {
		Properties properties = new Properties();
		try {
			properties.load(new FileReader(BINDING_PROPERTIES));
			Set<Entry<Object, Object>> set = properties.entrySet();
			for (Entry<Object, Object> entry : set) {
				try {
					Class<? extends LogEvent> eventClass = (Class<? extends LogEvent>) Class.forName((String) entry.getKey());
					Class<? extends LogAcceptor> la = (Class<? extends LogAcceptor>) Class.forName((String) entry.getValue());
					registerLogger(eventClass, la.newInstance());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public synchronized static GlobalLogger getInstance() {
		return instance;

	}

	@SuppressWarnings("unchecked")
	public void show(LogEvent le) {
		Class<? extends LogEvent> clazz = le.getClass();
		while (true) {
			LogAcceptor acceptor = acceptors.get(clazz);
			if (acceptor != null) {
				acceptor.show(le);
				break;
			} else if (LogAcceptor.class.equals(clazz)) {
				//TODO: process default log action
				break;
			} else {
				clazz = (Class<? extends LogEvent>) clazz.getSuperclass();
			}
		}
	}

	public void registerLogger(Class<? extends LogEvent> clazz, LogAcceptor la) {
		acceptors.put(clazz, la);
	}
	
	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		
		
		getInstance().show(new LogEvent(Types.INFORMATION, "Blah"));
		getInstance().show(new CacheEvent());
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		getInstance().show(new LogEvent(Types.INFORMATION, "1232132131"));
		getInstance().show(new LogEvent(Types.INFORMATION, "123321"));
		getInstance().show(new LogEvent(Types.INFORMATION, "13131"));
		getInstance().show(new LogEvent(Types.INFORMATION, "131"));
		try {
			Thread.sleep(20);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		getInstance().show(new CacheEvent());
		System.exit(0);
	}

}
